import time

numQueue = [1, 2, 3, 4, 5, 6, 7, 8, 9]
resultStack = []
checkPoint = [2, 5, 6, 7, 8]
SIZE = input()
try:
    SIZE = int(SIZE)
except:
    print("error!")
    quit()

if SIZE == 2:
    print("error!")
    quit()

numQueue = [x for x in range(1, SIZE*SIZE+1)]
resultStack = []
checkPoint = []
try_temp = 0
for i in range(SIZE):
    for j in range(SIZE):
        if i == SIZE-1 or j == SIZE-1:
            checkPoint.append(try_temp)
        try_temp += 1


SUM = sum(numQueue)/SIZE

board = [[0 for r in range(SIZE)] for c in range(SIZE)]


def GetRowColFromIndex(idx):
    r = int(idx / SIZE)
    c = int(idx % SIZE)
    return r, c

# 当前要放置的数字是否合法


def IsFillingValueValid(cur_index, val):
    global checkPoint, board
    if not cur_index in checkPoint:
        # 不是check_point的话就随便放
        return True

    r, c = GetRowColFromIndex(cur_index)

    # 是check_point的话要进行合法性校验
    if cur_index in checkPoint[:SIZE-2]:
        if sum(board[r]) + val == SUM:
            return True
    elif cur_index == checkPoint[SIZE-1]:
        if sum([board[x][c] for x in range(SIZE-1)]) + val == SUM and sum([board[x][y] for x in range(0, SIZE) for y in range(SIZE-1, 0, -1)]) + val == SUM:
            return True
    elif cur_index in checkPoint[SIZE-1:-2]:
        if sum([board[x][c] for x in range(SIZE-1)]) + val == SUM:
            return True
    elif cur_index == checkPoint[-1]:
        if sum([board[x][c] for x in range(SIZE-1)]) + val == SUM and sum(board[r]) + val == SUM and sum([board[x][x] for x in range(SIZE)]) + val == SUM:
            return True

    return False

# 获取比输入数字大1且没有使用过的数字


def GetBiggerUnusedNum(num):
    while num < max(numQueue):
        num += 1

        if num in numQueue:
            return num

    # 没有找到符合要求的数字
    return -1


def CalcCheckPointNum(curIndex):
    global board, numQueue
    r, c = GetRowColFromIndex(curIndex)
    ret = -1
    if curIndex in checkPoint[:SIZE-2]:
        cp = SUM - sum(board[r])
        if cp in numQueue:
            ret = cp
    elif curIndex == checkPoint[SIZE-1]:
        cp = SUM - sum([board[x][c] for x in range(SIZE-1)])
        if cp in numQueue and cp + sum([board[x][y] for x in range(0, SIZE) for y in range(SIZE-1, 0, -1)]) == SUM:
            ret = cp
    elif curIndex in checkPoint[SIZE-1:-2]:
        cp = SUM - sum([board[x][c] for x in range(SIZE-1)])
        if cp in numQueue:
            ret = cp
    elif curIndex == checkPoint[-1]:
        cp = SUM - sum(board[r])
        if cp in numQueue and cp + sum([board[x][c] for x in range(SIZE-1)]) == cp + sum([board[x][x] for x in range(SIZE)]) == SUM:
            ret = cp

    return ret


def PutNum(curIndex, num):
    global board, numQueue
    r, c = GetRowColFromIndex(curIndex)
    board[r][c] = num
    resultStack.append((curIndex, num))
    numQueue.remove(num)


def main():
    global board, numQueue
    # 当前要填的格子
    curIndex = 0

    while len(numQueue) > 0:
        # 如果index in checkPoint，则自动补最后一个数字
        r, c = GetRowColFromIndex(curIndex)
        needRollBack = False
        if board[r][c] == 0:
            num = min(numQueue)
            if IsFillingValueValid(curIndex, num) == True:
                # 合法包括两种情况，一种是非checkpoint, 一种是合法的checkpoint
                PutNum(curIndex, num)
            else:
                # 否则计算checkpoint上究竟应该放数字几
                # 如果所需的数字不存在则触发回溯
                checkPointNum = CalcCheckPointNum(curIndex)
                if checkPointNum == -1:
                    needRollBack = True
                else:
                    PutNum(curIndex, checkPointNum)

            if needRollBack == True:
                # 不合法，进行回溯
                while True:
                    info = resultStack.pop()
                    rollBackIndex = info[0]
                    num = info[1]
                    rr, cc = GetRowColFromIndex(rollBackIndex)
                    numQueue.append(num)
                    nextNum = GetBiggerUnusedNum(num)
                    if (nextNum != -1 and IsFillingValueValid(rollBackIndex, nextNum) == True):
                        PutNum(rollBackIndex, nextNum)
                        break

                    # 如果nextNum == -1，则清理[rr][cc]继续回溯
                    board[rr][cc] = 0
                curIndex = rollBackIndex + 1
            else:
                curIndex += 1

    for r in range(SIZE):
        print(board[r])


start_time = time.time()
main()
total_time = time.time() - start_time
print(total_time)
